
run();

function run()
{
   // hook();
    hook_phone_state();
    hook_dynamic_register_permission();
    hook_camera();
    hook_location();
    hook_account_manager();
    hook_audio_record();
    hook_sms();
};

// setImmediate(function ()
// {
//     setTimeout(run,1000)
//     console.log("wait...")
// });


rpc.exports =
{
    exit: function (name)
    {
       send("exit")
    },
};

function hook()
{
    Java.perform(function ()
    {
        var MainActivity = Java.use('com.hx.hxsocket.MainActivity');
        MainActivity.test.implementation = function ()
        {
            send(format(1,"test","android.permission.READ_PHONE_STATE",get_stack()))
            return this.test();
        };
    });
}

function hook_sms()
{
    Java.perform(function()
    {
        var sm = Java.use('android.telephony.SmsManager');
        sm.sendTextMessage.implementation = function (str1, str2, str3, pendingIntent1, pendingIntent2)
        {
            send(format(1,"sendTextMessage","android.permission.SEND_SMS",get_stack()))
            return this.sendTextMessage(str1, str2, str3, pendingIntent1, pendingIntent2);
        };
    });
}

function hook_audio_record()
{
    Java.perform(function ()
    {
        var ar = Java.use('android.media.AudioRecord');

        ar.startRecording.overload().implementation = function ()
        {
            send(format(1,"startRecording","android.permission.RECORD_AUDIO",get_stack()))
            return this.startRecording();
        };

        ar.startRecording.overload('android.media.MediaSyncEvent').implementation = function (mse)
        {
            send(format(1,"startRecording","android.permission.RECORD_AUDIO",get_stack()))
            return this.startRecording(mse);
        };
    });
}

function hook_location()
{
    Java.perform(function ()
    {
        var am = Java.use('android.location.LocationManager');
        am.getLastKnownLocation.implementation = function (string)
        {
            send(format(1,"getLastKnownLocation","android.permission.ACCESS_FINE_LOCATION",get_stack()))
            return this.getLastKnownLocation(string);
        };
    });
}

function hook_account_manager()
{
    Java.perform(function ()
    {
        var am = Java.use('android.accounts.AccountManager');
        am.getAccounts.implementation = function ()
        {
            send(format(1,"getAccounts","android.permission.GET_ACCOUNTS",get_stack()))
            return this.getAccounts();
        };
    });
}

function hook_camera()
{
    Java.perform(function ()
    {
        var cm = Java.use('android.hardware.camera2.CameraManager');
        cm.getCameraCharacteristics.implementation = function (string)
        {
            send(format(1,"getCameraCharacteristics","android.permission.CAMERA",get_stack()))
            return this.getCameraCharacteristics(string);
        };
    });
}

function hook_dynamic_register_permission()
{
    Java.perform(function ()
    {
        var ac = Java.use('android.app.Activity');
        ac.requestPermissions.overload('[Ljava.lang.String;', 'int').implementation = function (string_ary, mumber)
        {
            var ary = new_json_array();

            for (var i = 0; i < string_ary.length; i++)
            {
                ary.put(string_ary[i]);
            }
            send(format(0,"requestPermissions","",ary.toString()))

            return this.requestPermissions(string_ary, mumber);
        };
    });
}

function hook_phone_state()
{
    Java.perform(function ()
    {
        var tm = Java.use('android.telephony.TelephonyManager');
        tm.getLine1Number.overload().implementation = function ()
        {
            send(format(1,"getLine1Number","android.permission.READ_PHONE_STATE",get_stack()))
            return this.getLine1Number();
        };

        tm.getDeviceId.overload('int').implementation = function (number)
        {
            send(format(1,"getLine1Number","android.permission.READ_PHONE_STATE",get_stack()))
            return this.getDeviceId(number);
        };

        tm.getDeviceId.overload().implementation = function ()
        {
            send(format(1,"getDeviceId","android.permission.READ_PHONE_STATE",get_stack()))
            return this.getDeviceId();
        };

        tm.getDeviceId.overload('int').implementation = function (number)
        {
            send(format(1,"getDeviceId","android.permission.READ_PHONE_STATE",get_stack()))
            return this.getDeviceId(number);
        };

        tm.getImei.overload().implementation = function ()
        {
            send(format(1,"getImei","android.permission.READ_PHONE_STATE",get_stack()))
            return this.getImei();
        };

        tm.getImei.overload('int').implementation = function (number)
        {
            send(format(1,"getImei","android.permission.READ_PHONE_STATE",get_stack()))
            return this.getImei(number);
        };

        tm.getSubscriberId.overload().implementation = function ()
        {
            send(format(1,"getSubscriberId","android.permission.READ_PHONE_STATE",get_stack()))
            return this.getSubscriberId();
        };

        tm.getSubscriberId.overload('int').implementation = function (number)
        {
            send(format(1,"getSubscriberId","android.permission.READ_PHONE_STATE",get_stack()))
            return this.getSubscriberId(number);
        };

        var wf = Java.use('android.net.wifi.WifiInfo');
        wf.getMacAddress.implementation = function ()
        {
            send(format(1,"getMacAddress","android.permission.READ_PHONE_STATE",get_stack()))
            return this.getMacAddress();
        };

        var ni = Java.use('java.net.NetworkInterface');
        ni.getHardwareAddress.implementation = function ()
        {
            send(format(1,"getMacAddress","android.permission.READ_PHONE_STATE",get_stack()))
            return this.getHardwareAddress();
        };

    });
}

function new_json_object(args)
{
    var json = Java.use('org.json.JSONObject').$new();
    return json;
}

function new_json_array(args)
{
    var json_ary = Java.use('org.json.JSONArray').$new();
    return json_ary;
}

function format(type, fun_name, permission,content)
{
    var json = new_json_object();
    json.put("type",type);
    json.put("permission",permission);
    json.put("name",fun_name);
    json.put("content",content);
    json.put("time_stamp",get_time());
    return json.toString();
}

function get_stack()
{
    var ex = Java.use("java.lang.Throwable").$new();
    var stack_elements = ex.getStackTrace();
    var json_ary = null;
    if (null != stack_elements && stack_elements.length > 0)
    {
        json_ary = new_json_array();
        for (var i = 1; i < stack_elements.length; i++)
        {
            json_ary.put(stack_elements[i].getClassName());
        }
    }
    return json_ary;
}

function get_time()
{
    return Java.use("java.lang.String").$new().valueOf(Java.use("java.lang.System").currentTimeMillis());
}